import {
    Asset, AssetManager, JsonAsset, Node, Prefab, SceneAsset, Sprite, SpriteFrame, Texture2D,
    UITransform, assetManager, instantiate, resources, sys
} from "cc";
import { Logger } from "./Logger";
import { BundleConfig } from "../config/BundleConfig";
import { UI_Config } from "./UI_Config";

export class ResourceManager {

    private static _instance: ResourceManager;
    static get instance(): ResourceManager {
        if (!ResourceManager._instance) {
            ResourceManager._instance = new ResourceManager();
            ResourceManager._instance.init();
        }
        return ResourceManager._instance;
    }

    public bundleMap: Map<string, AssetManager.Bundle> = new Map<string, AssetManager.Bundle>()

    async init() {
        this.bundleMap.set(BundleConfig.main, resources)
    }

    public loadBundle(bundleName: string, callback: Function = null) {
        Logger.log("loadBundle=====", bundleName)
        assetManager.loadBundle(bundleName, (err: Error, bundle: AssetManager.Bundle) => {
            if (err) {
                Logger.error("loadBundle==error===", bundleName, err)
            } else {
                Logger.log("loadBundle====suc=", bundleName, bundle)
                this.bundleMap.set(bundleName, bundle);
                callback && callback(bundle)
            }
        });
    }

    /**
     *  根据资源路径以及 bundle 返回资源 
     * @param path 
     * @param bundle 
     * @param progressCallback 
     * @param finishCallback 
     * @returns 
     */
    public load(path: any, bundle: AssetManager.Bundle = resources,
        progressCallback: Function = null, finishCallback: Function = null) {
        if (!bundle) {
            bundle = resources
        }
        bundle.load(path, (completedCount: number, totalCount: number, item: any) => {
            progressCallback && progressCallback(completedCount, totalCount, item);
        }, (err, resource: any[]) => {
            if (err) {
                Logger.error("load error===", path, err)
                return;
            }
            finishCallback && finishCallback(resource);
        });
    }

    public preload(path: any, bundle: AssetManager.Bundle = resources,
        progressCallback: Function = null, finishCallback: Function = null) {
        if (!bundle) {
            bundle = resources
        }
        bundle.preload(path, (completedCount: number, totalCount: number, item: any) => {
            progressCallback && progressCallback(completedCount, totalCount, item);
        }, (err, resource: any[]) => {
            if (err) {
                Logger.error("preload error===", path, err)
                return;
            }
            finishCallback && finishCallback(resource);
        });
    }

    /**
     * 释放 指定资源 
     * @param asset 
     */
    public releaseAsset(asset: Asset) {
        assetManager.releaseAsset(asset)
    }

    /**
     * 释放 bundle 包下某些资源 
     * @param paths 
     * @param bundle 
     */
    public releaseList(paths: string[], bundle: AssetManager.Bundle) {
        for (let i = 0; i < paths.length; i++) {
            this.release(paths[i], bundle);
        }
    }

    /**
     * 释放 bundle 包下某个资源 
     * @param path 
     * @param bundle 
     */
    public release(path: string, bundle: AssetManager.Bundle) {
        bundle.release(path)
    }

    /**
     *  根据uiConfig 释放
     * @param uiConfig 
     */
    public releaseByUiConfig(uiConfig: UI_Config) {
        let bundle: AssetManager.Bundle = this.bundleMap.get(uiConfig.bundleName)
        this.release(uiConfig.path, bundle)
    }


    /**
     * 加载远程资源 
     * @param url 
     * @param callback 
     */
    public loadRemoteRes(url: string, param: object = {}, callback: Function = null) {
        assetManager.loadRemote(url, param, (err, resource: Asset) => {
            callback && callback(resource)
        })
    }

    /**
     * 加载远程图片
     * @param url 
     * @param param 
     * @param callback 
     */
    public loadRemoteImg(url: string, param: object = {}, callback: Function = null) {
        this.loadRemoteRes(url, param, (imageAsset) => {
            if (imageAsset) {
                const spriteFrame = new SpriteFrame();
                const texture = new Texture2D();
                texture.image = imageAsset;
                spriteFrame.texture = texture;
                callback(spriteFrame)
            }
        });
    };

    /**
     * 根据 sprite 路径加载远程图片
     */
    public loadRemoteImgBySprite(url: string, sprite: Sprite, width: number = 0, height: number = 0,
        param: object = {}, callback: Function = null) {
        if (width > 0 && height > 0) {
            url += "?w=" + width + "&h=" + height
        }
        this.loadRemoteRes(url, param, (imageAsset) => {
            if (imageAsset) {
                const spriteFrame = new SpriteFrame();
                const texture = new Texture2D();
                texture.image = imageAsset;
                spriteFrame.texture = texture;
                sprite.spriteFrame = spriteFrame
                if (width > 0) {
                    sprite.node.getComponent(UITransform).width = width
                }
                if (height > 0) {
                    sprite.node.getComponent(UITransform).height = height
                }
                callback && callback(spriteFrame)
            }
        });

    }
}